use crate::{
    common,
    handlers::{self, menu},
    tables::user::{TbUser, User},
};
use actix_web::{delete, get, post, web, HttpMessage, HttpRequest, HttpResponse, Responder};
use serde::{Deserialize, Serialize};
use serde_json::json;

#[derive(Debug, Serialize, Deserialize)]
pub struct Get {
    appid: Option<String>,
    username: Option<String>,
    id: Option<String>,
    name: Option<String>,
    role: Option<String>,
}

#[get("")]
async fn get(page: web::Query<common::QueryPage>, query: web::Query<Get>) -> impl Responder {
    common::ResData::<User>::from_page(TbUser::get_users(&page, &query).await)
        .trans(|user| {
            user.finger_l0 = Some("ENROLL".to_owned());
            user.finger_l1 = Some("ENROLL".to_owned());
            user.finger_l2 = Some("ENROLL".to_owned());
            user.finger_l3 = Some("ENROLL".to_owned());
            user.finger_l4 = Some("ENROLL".to_owned());
            user.finger_r0 = Some("ENROLL".to_owned());
            user.finger_r1 = Some("ENROLL".to_owned());
            user.finger_r2 = Some("ENROLL".to_owned());
            user.finger_r3 = Some("ENROLL".to_owned());
            user.finger_r4 = Some("ENROLL".to_owned());
        })
        .resp_json()
}

#[post("")]
async fn post() -> impl Responder {
    "post"
}

#[delete("")]
async fn delete() -> impl Responder {
    "delete"
}

#[get("/current")]
async fn current(req: HttpRequest) -> impl Responder {
    let extensions = req.extensions();
    let username = extensions.get::<String>();
    if username.is_none() {
        return Err(handlers::unauthorized_response("请先登录"));
    }

    let user = TbUser::get_user(username.unwrap().as_str()).await;
    if let Err(e) = user {
        return Err(handlers::unauthorized_response(e.to_string().as_str()));
    }
    let user = user.unwrap();
    if user.is_none() {
        return Err(handlers::unauthorized_response("用户不存在"));
    }

    let user = &mut User::from(user.unwrap());

    let menus = menu::get_role_menus(user.role_id);
    if menus.is_none() {
        return Err(handlers::unauthorized_response("角色不存在"));
    }

    user.menu_data = Some(menus.unwrap());

    Ok(HttpResponse::Ok().body(
        json!({
            "success": true,
            "data": &user,
        })
            .to_string(),
    ))
}

#[get("/all")]
async fn all() -> impl Responder {
    common::ResData::<User>::from_data(TbUser::get_all_users().await).resp_json()
}

pub fn routes(cfg: &mut web::ServiceConfig) {
    cfg.service(
        web::scope("/user")
            .service(get)
            .service(post)
            .service(delete)
            .service(current)
            .service(all),
    );
}

#[cfg(test)]
pub mod tests {
    use crate::{handlers::user, utils::mysql};
    use actix_web::{test, App};
    use serde_json::Value;

    #[actix_web::test]
    async fn test_get_user() {
        mysql::init_pool().await;

        let app = test::init_service(App::new().configure(user::routes)).await;

        let req = test::TestRequest::get()
            .uri("/user?page_size=5&&username=test")
            .to_request();

        let resp = test::call_service(&app, req).await;
        let status = resp.status();
        println!("resp status is {:?}", status);
        let resp_body = test::read_body(resp).await;
        let json_value: Value = serde_json::from_slice(&resp_body).unwrap();
        println!("restp body is {}", json_value);
        assert!(status.is_success());
    }

    #[actix_web::test]
    async fn test_get_all_users() {
        mysql::init_pool().await;

        let app = test::init_service(App::new().configure(user::routes)).await;

        let req = test::TestRequest::get().uri("/user/all").to_request();

        let resp = test::call_service(&app, req).await;
        let status = resp.status();
        println!("resp status is {:?}", status);
        let resp_body = test::read_body(resp).await;
        println!("restp body is {:?}", resp_body);
        assert!(status.is_success());
    }
}
